import React, {
  createContext,
  ReactNode,
  useState,
  useContext,
  useMemo,
  useEffect,
} from 'react';
import { getAllFieldsCities } from '@/services';
import type { CityInfo, CityStoreContextApi } from '@/types/store';

const CityStoreContext = createContext<CityStoreContextApi>({
  getState: () => ({
    cityInfo: null,
    cityList: [],
  }),
  setCityInfo: () => {},
  setCityList: () => {},
  addCity: () => {},
  removeCity: () => {},
  refreshAllCities: async () => {},
});

export const CityStoreContextProvider = (props: CityStoreContextApi & { children: ReactNode }) => (
  <CityStoreContext.Provider value={props}>
    {props.children}
  </CityStoreContext.Provider>
);

export function useCityStoreProvide(): CityStoreContextApi {
  const [cityInfo, setCityInfo] = useState<CityInfo | null>(null);
  const [cityList, setCityList] = useState<Array<CityInfo>>([]);

  const _getState = () => ({
    cityInfo,
    cityList,
  });

  const _setCityInfo = (newCityInfo: CityInfo) => {
    setCityInfo(newCityInfo);
  }

  const _setCityList = (newCityList: Array<CityInfo>) => {
    setCityList(newCityList);
  }

  const _addCity = (city: CityInfo) => {
    setCityList((prev) => [...prev, city]);
  }

  const _removeCity = (key: string) => {
    setCityList((prev) => prev.filter((item) => item.key !== key));
  }
  
  const refreshAllCities = async () => {
    try {
      const { code, message, data } = await getAllFieldsCities();
      if (code !== 0) {
        throw new Error(message);
      }
      const newCityList: CityInfo[] = data.map((item: { name: string; aliasName: string }) => ({
        key: item.name,
        name: item.aliasName
      }));
      setCityList(newCityList);
    } catch (e) {
      console.log('請求城市信息失敗: %s', e instanceof Error ? e.message : 'Unknown error');
    }
  }

  useEffect(() => {
    refreshAllCities();
  }, []);

  return {
    getState: _getState,
    setCityInfo: _setCityInfo,
    setCityList: _setCityList,
    addCity: _addCity,
    removeCity: _removeCity,
    refreshAllCities,
  };
}

export function useCityStoreInject() {
  return useContext(CityStoreContext);
}

export function useCityInfo() {
  const { getState } = useContext(CityStoreContext);

  const currentCityInfo = useMemo<Partial<CityInfo>>(() => {
    const { cityInfo } = getState();
    return cityInfo ?? {};
  }, [getState]);

  return currentCityInfo;
}

export function useCityList() {
  const { getState } = useContext(CityStoreContext);

  const cityList = useMemo<Array<CityInfo>>(() => {
    const { cityList } = getState();
    return cityList ?? [];
  }, [getState]);

  return cityList;
}
